/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import java.beans.XMLEncoder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gson.Gson;
import empregado.Empregado;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.lang.Object;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.TreeSet;
/**
 *
 * @author Zanoni
 */
public class DAOJSON implements DAOGenerico{
    private String path="database.";
    private Class Object;
    
     /**
     * Busca um objeto e retorna null se não achar
     * @param   objeto que deseja buscar.
     * @return  objeto encontrado.
     */
    @Override
    public Object buscar(Object obj) throws Exception{
        Class classe=obj.getClass();
        Collection array=new ArrayList(); 
        array=retornaElementos(classe);            
        for(Object o : array){                
            if( obj.equals(o) ){
                return o;
            }                   
        }                   
        armazenaElementos(array,classe);             
        return null;
    }
    
    /**
     * Deleta um objeto do json e retorna true se achar e false se não achar
     * @param   objeto que deseja buscar.
     * @return  boolean se achou o objeto.
     */
    @Override
    public boolean deletar(Object obj) throws Exception{
        Class classe=obj.getClass();
        Collection array=new ArrayList();     
        array=retornaElementos(classe);
        boolean retorno=false;
        for(Object o : array){                
            if( obj.equals(o) ){ 
                array.remove(o);
                retorno=true;
                break;                
            }                   
        }                   
        armazenaElementos(array,classe);             
        return retorno;
    }
    /**
     * Salva um objeto em json , se ele ja existeir ele altera o objeto, se não ele insere o objeto
     * @param   objeto que deseja salvar.
     */
    @Override
    public void salvar(Object obj) throws Exception {
        if(buscar(obj)!=null){
            alterar(obj);
        }else{
            inserir(obj);
        }      
    }
    /**
     * Insere um objeto no arquivo
     * @param   objeto que deseja inserir.
     */
    private void inserir(Object obj) throws Exception{
        Class classe=obj.getClass();
        Collection array=new ArrayList();      
        array=retornaElementos(classe);    
        array.add(obj);      
        armazenaElementos(array,classe);    
    }
    
    /**
     * Alterar um objeto no arquivo
     * @param   objeto que deseja alterar.
     */
    private void alterar(Object obj) throws Exception{
        Class classe=obj.getClass();
        Collection array=new ArrayList();       
        array=retornaElementos(classe);            
        for(Object o : array){            
            if( obj.equals(o) ){   
                array.remove(o);
                array.add(obj);
                break;
            }                   
        }                   
        armazenaElementos(array,classe);             
       
    }
     
    /**
     * Retorna um grupo de objetos que encaichm na consulta 
     * @param objeto com os campos a serem consultados.
     * @return grupo de objetos.
     */
    @Override
    public Collection consultar(Object obj) throws Exception{
        Class classe=obj.getClass();
        Collection array=new ArrayList();
        Collection arrayFinal=new ArrayList();
        Collection metodos=new ArrayList();
           for( Field f : classe.getDeclaredFields() ){
            String nomeAtrributo=f.getName();
            String nomeDoGet="get"+nomeAtrributo.substring(0,1).toUpperCase()+nomeAtrributo.substring(1);
            Method m=classe.getMethod(nomeDoGet, new Class[0]);
            try{
                if(m.invoke(obj, new Object[0])!=null){                
                    metodos.add(m);
                }
            }catch (Exception ex){
                //pois eh...
            }
        }
        
        array=retornaElementos(classe);
        for(Object o : array){
            boolean pode=true;
            for(Object m : metodos){
                Method metodo=(Method)m;
                if( metodo.invoke(obj, new Object[0]).equals(metodo.invoke(o, new Object[0])) ){
                }else{
                    pode=false;
                }
            }
            if(pode){
               arrayFinal.add(o);
            }
        }

        return array;
    }
     /**
     * Armazena um array no arquivo
     * @param Array se objetos a serem armazenados.
     * @param Classe dos objetos.
     */   
    private void armazenaElementos(Collection array,Class classe) throws IOException{    
        PrintWriter writer;
        String json="";
        Gson gson = new Gson();
        
        json = gson.toJson(array,array.getClass());
        writer = new PrintWriter(new FileWriter(path+classe.getCanonicalName()+".json"));
        writer.println(json);
        writer.close();
    }
    
     /**
     * Retorna um array de objetos do arquivo
     * @param Classe dos objetos.
     */   
    private Collection retornaElementos(Class classe) throws IOException{
        FileReader arquivo;
        BufferedReader leitor; 
        String json="";
        Gson gson = new Gson();
        ArrayList<String> arrayJson=new ArrayList<String>();
        Collection arrayFinal=new ArrayList();
        try {
            arquivo = new FileReader(path+classe.getCanonicalName()+".json");        
            leitor = new BufferedReader(arquivo);
            String linha="";
            while (leitor.ready()) {
                linha = leitor.readLine();
                json = json.concat(linha);
            }
            //gson.fromJson( json, ArrayList<Object>.class );
            /*Solução mutante, não consegui fazer isso de maneira correta*/
            String tempJson="";
            char[] charArray=json.toCharArray();
            int level=0;
            for(int i=0;i<charArray.length;i++){
                if(charArray[i]=='{'){
                    level++;
                    tempJson+=charArray[i];
                }else if(charArray[i]=='}'){
                    level--;
                    tempJson+=charArray[i];
                    if(level==0){
                        arrayJson.add(tempJson);
                        tempJson="";
                    }
                }else{
                    if(level>0){
                        tempJson+=charArray[i];
                    }
                }
            }
            for(String ps : arrayJson){
                arrayFinal.add( gson.fromJson(ps,classe) );
            }
        } catch (FileNotFoundException ex) {
            //arquivo não foi encontrado, retorna o array vazio ...
        }
        //System.out.println(arrayFinal);
        return arrayFinal;
    } 
    
    
}
